package com.zf.common.web.config;

import feign.RequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Objects;


/**
 * <pre>
 * feign官方文档：
 * 1、https://spring.io/projects/spring-cloud-openfeign#learn
 * 2、https://docs.spring.io/spring-cloud-openfeign/reference/spring-cloud-openfeign.html#spring-refreshscope-support
 *
 * 该类用来解决feign调用的一些问题
 * </pre>
 */
@Configuration
public class FeignConfig {

    /**
     * 解决feign同步调用请求头丢失的问题，如果不需要使用到当前线程的request,则此问题可以不用考虑。
     * 解决方法：定义一个拦截器{@link RequestInterceptor}，手动添加原请求的header信息
     */
    @Bean("allHeaderRequestInterceptor")
    RequestInterceptor allHeaderRequestInterceptor() {
        return requestTemplate -> {
            // 过滤器 org.springframework.web.filter.RequestContextFilter.doFilterInternal() 会创建 ServletRequestAttributes
            // 此处直接获取即可
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                Enumeration<String> headerNames = request.getHeaderNames();
                if (headerNames != null) {
                    while (headerNames.hasMoreElements()) {
                        String headerName = headerNames.nextElement();
                        String headerValue = request.getHeader(headerName);
                        if (!requestTemplate.headers().containsKey(headerName)) {
                            requestTemplate.header(headerName, headerValue);
                        }
                    }
                }
            }
        };
    }

    /**
     * 解决feign同步调用 TRACE_ID 请求头丢失的问题
     */
    @Bean("traceIdRequestInterceptor")
    RequestInterceptor traceIdRequestInterceptor() {
        return requestTemplate -> {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (attributes != null) {
                HttpServletRequest request = attributes.getRequest();
                // 从请求头中获取 TRACE_ID
                String traceId = request.getHeader(BasicConstants.TRACE_ID);
                if (!StringUtils.hasText(traceId)) {
                    // 如果没有在请求头中获取 TRACE_ID，则去 request的Attribute 中取 TRACE_ID
                    Object attribute = request.getAttribute(BasicConstants.TRACE_ID);
                    traceId = Objects.isNull(attribute) ? null : String.valueOf(attribute);
                }
                // 如果新请求中已经有 TRACE_ID 请求头，则不做任何处理
                if (StringUtils.hasText(traceId) && !requestTemplate.headers().containsKey(BasicConstants.TRACE_ID)) {
                    // 设置 TRACE_ID 请求头
                    requestTemplate.header(BasicConstants.TRACE_ID, traceId);
                }
            }
        };
    }

}
